//创建用户相关的小仓库
import { defineStore } from "pinia";
//引入接口
import {reqLogin, reqUserInfo, reqLogout} from "@/api/user";
//引入登陆相关的参数ts类型
import type {loginFormData, loginResponseData, UserInfoResponseData,LogoutResponseData} from "@/api/user/type";
import type {UserState} from "@/stores/modules/types/type.ts"
//引入操作本地存储的工具方法
import {SET_TOKEN, GET_TOKEN, REMOVE_TOKEN} from "@/utils/token.ts"
//引入路由(常量路由)
import {constantRoute,anyRoute,asyncRoute} from "@/router/routes.ts"
import router from "@/router";
//引入深拷贝方法
//@ts-ignore
import cloneDeep from 'lodash/cloneDeep'
//用于过滤当前用户需要展示的异步路由
function filterAsyncRoute(asnycRoute: any, routes: any) {
    return asnycRoute.filter((item: any) => {
        if (routes.includes(item.name)) {
            if (item.children && item.children.length > 0) {
                //硅谷333账号:product\trademark\attr\sku
                item.children = filterAsyncRoute(item.children, routes);
            }
            return true;
        }
    })
}
//创建用户小仓库
let useUserStore = defineStore("User", {
    //小仓库存储数据地方
    state: ():UserState => {
        return {
            token: GET_TOKEN(), //用户唯一标识token
            menuRoutes: constantRoute,//仓库存储生成菜单需要数组(路由)
            username: '',
            avatar: '',
            buttons: []//用于判断按钮权限
        }
    },
    //处理异步或逻辑的地方
    actions: {
        //用户登录的方法
        async userLogin(data:loginFormData){
            REMOVE_TOKEN();//登录前清除一下本地存储，防止token过期
            //登录请求
            let result:loginResponseData = await reqLogin(data);
            //登录请求:成功200->token
            //登录请求:失败201->登录失败错误的信息
            if (result.code == 200) {
                //pinia仓库存储一下token
                //由于pinia|vuex存储数据其实利用js对象
                this.token = (result.data as string);//表示将 result.data.token 强制视为 string 类型。
                //本地存储持久化存储一份
                SET_TOKEN((result.data as string));
                //能保证当前async函数返回一个成功的promise
                return 'ok';//表示登录成功，允许继续执行后续操作。
            }else{
                return Promise.reject(new Error(result.data));
            }
        },
        //获取用户信息方法
        async userInfo(){
            let result: UserInfoResponseData = await reqUserInfo();
            if(result.code == 200){
                this.username = result.data.username;
                this.avatar = result.data.avatar;
                this.buttons = result.data.buttons;

                console.log('获取到的用户信息:', result.data);
                console.log('后端返回的路由:', result.data.routes);
                console.log('用户权限列表:', result.data.buttons);

                //计算当前用户需要展示的异步路由
                let userAsyncRoute = filterAsyncRoute(cloneDeep(asyncRoute), result.data.routes);

                console.log('过滤后的异步路由:', userAsyncRoute);

                //菜单需要的数据整理完毕
                this.menuRoutes = [...constantRoute, ...userAsyncRoute, ...anyRoute];

                console.log('最终的菜单路由:', this.menuRoutes);

                //目前路由器管理的只有常量路由:用户计算完毕异步路由、任意路由动态追加
                [...userAsyncRoute, ...anyRoute].forEach((route: any) => {
                    router.addRoute(route);
                });

                return 'ok';
            }else{
                return Promise.reject(new Error(result.message));
            }
        },
        //退出登录方法
        async userLogout(){
            try {
                // 调用退出登录接口
                let result:LogoutResponseData = await reqLogout();

                // 只有接口调用成功才清除本地数据
                if (result.code === 200) {
                    REMOVE_TOKEN();
                    this.token = '';
                    this.username = '';
                    this.avatar = '';
                    this.buttons = [];
                    return 'ok';
                } else {
                    // 接口返回失败，抛出错误
                    return Promise.reject(new Error(result.message || '退出登录失败'));
                }
            } catch (error) {
                // 网络错误或其他错误，不清除本地数据
                console.error('退出登录接口调用失败:', error);
                return Promise.reject(error);
            }
        }
    },
    getters: {}
})
//对外暴露获取小仓库方法
export default useUserStore;
